import _pickle as cPickle
import numpy as np
from scipy.io.wavfile import read
#from sklearn.mixture import GMM
from sklearn.mixture import GaussianMixture as GMM
from speakerfeatures import extract_features
import warnings
import os
warnings.filterwarnings("ignore")


#path to training data
source   = "audio_wav"

#path where training speakers will be saved
dest = "bear_models"

file_paths = os.listdir(source)
count = 1

# Extracting features for each speaker (5 files per speakers)
features = np.asarray(())
for path in file_paths:
    people_path = os.path.join(source, path)
    len_ple = len(os.listdir(people_path))
    for wav in os.listdir(people_path):
        sr,audio = read(os.path.join(people_path ,wav))
    # extract 40 dimensional MFCC & delta MFCC features
        vector   = extract_features(audio,sr)

        if features.size == 0:
            features = vector
        else:
            features = np.vstack((features, vector))
        # when features of 5 files of speaker are concatenated, then do model training
        if count == len_ple:
            #gmm = GMM(n_components = 16, n_iter = 200, covariance_type='diag',n_init = 3)
            gmm = GMM(n_components = 22, max_iter = 400 , covariance_type='full',n_init = 4)
            gmm.fit(features)

            # dumping the trained gaussian model
            picklefile = wav.split(".")[0]+".gmm"
            cPickle.dump(gmm,open(os.path.join(dest ,picklefile),'wb'))
            print('+ modeling completed for speaker:',picklefile," with data point = ",features.shape)
            features = np.asarray(())
            count = 0
        print(wav , "finish")
        count = count + 1

import datetime
starttime = datetime.datetime.now()

import os
import _pickle as cPickle
import numpy as np
from scipy.io.wavfile import read
from speakerfeatures import extract_features
import warnings
warnings.filterwarnings("ignore")
import time

modelpath = "bear_models/"
file_paths = "audio_wav_test"

gmm_files = [os.path.join(modelpath,fname) for fname in
              os.listdir(modelpath) if fname.endswith('.gmm')]

#Load the Gaussian gender Models
models    = [cPickle.load(open(fname,'rb')) for fname in gmm_files]
speakers   = [fname.split("\\")[-1].split(".gmm")[0].split("/")[1] for fname
              in gmm_files]

print(speakers)

#softmax
def softmax(x):
    return np.exp(x)/np.sum(np.exp(x),axis=0)

# Read the test directory and get the list of test audio files
fect_true = 0
fect_false = 0
pre_0_true = 0
pre_peo_true = 0
pre_peo_all = 0
for wav in os.listdir(file_paths):
    sr,audio = read(os.path.join(file_paths,wav))
    vector   = extract_features(audio,sr)
    #print(vector)
    log_likelihood = np.zeros(len(models))
    #print(log_likelihood)
    for i in range(len(models)):
        gmm    = models[i]         #checking with each model one by one
        scores = np.array(gmm.score(vector))
        log_likelihood[i] = scores.sum()
    winner = np.argmax(log_likelihood)
    if max(softmax(log_likelihood)) > 0.8: pre_speaker = speakers[winner]
    else : pre_speaker = 'Nobody'
    print(max(softmax(log_likelihood)))
    print(wav ,"\tdetected as - ", pre_speaker)
    test_wav_speaker = wav.split("1")[0]
    if test_wav_speaker in speakers : fect_true = fect_true + 1
    else : fect_false = fect_false + 1

    if test_wav_speaker == pre_speaker: pre_peo_true  = pre_peo_true  + 1
    elif pre_speaker == "Nobody" and test_wav_speaker not in speakers:  pre_0_true = pre_0_true + 1

    if pre_speaker != "Nobody": pre_peo_all = pre_peo_all + 1

print("总测试文件数量：",len(os.listdir(file_paths)) , "\n实际上是主人的数量：",fect_true , "实际上非主人的数量：",fect_false,
      "\n预测主人正确的数量：", pre_peo_true , "预测非主人正确的数量：" , pre_0_true ,
      "\n说话人识别准确率：" ,pre_peo_true/pre_peo_all , "说话人确认准确率：" ,(pre_peo_true + pre_0_true)/len(os.listdir(file_paths)) )

endtime = datetime.datetime.now()
print((endtime - starttime).seconds , 's')